<template>
  <el-dialog
    :model-value="visible"
    class="import-dialog_container"
    align-center
    @close="closeDialog"
    :close-on-click-modal="false"
    destroy-on-close
    draggable
    :close-on-press-escape="false"
  >
    <template #header>
      <div class="my-header">
        <div class="title">{{ title }}</div>
      </div>
    </template>
    <div class="upload_container" v-if="downloadUrl">
      <span class="fontClass">下载模板</span>
      <span class="tipsClass"
        >请按照模板内容进行填写导入,单次仅可上传一个文件，文件支持格式：xlsx，且文件大小不超过50MB</span
      >
      <el-button
        class="btnClass"
        type="primary"
        plain
        @click="downloadTemplate"
        v-loading="downloading"
        >下载空模板</el-button
      >
    </div>

    <el-upload
      ref="uploader"
      class="upload-action"
      action=""
      drag
      :multiple="false"
      accept=".xls, .xlsx"
      v-model:file-list="fileList"
      :on-change="beforeUpload"
      :auto-upload="false"
      :http-request="httpRequest"
      :on-exceed="handleExceed"
      :limit="1"
    >
      <el-icon class="el-icon--upload">
        <upload-filled />
        <template #file="{ file }">
          <span style="border: 1px red solid">{{ file }}</span>
        </template>
        <div class="upload__text">将文件拖入此处上传,或者点击此处添加文件上传</div>
      </el-icon>
    </el-upload>

    <template #footer>
      <span class="dialog-footer">
        <el-button @click="closeDialog">取消</el-button>
        <el-button type="primary" @click="onSubmit" :loading="loading">上传</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import {
  type UploadInstance,
  type UploadFile,
  type UploadFiles,
  type UploadUserFile,
  type UploadRequestOptions,
  ElMessage
} from 'element-plus'
import { UploadFilled } from '@element-plus/icons-vue'
import { ref } from 'vue'
import { useExport } from '@/hooks/useExport'

type ImportRes = {
  code: number
  msg: string
}

type Props = {
  visible: boolean
  downloadUrl: string
  importApi: (data: FormData) => Promise<ImportRes>
  fileName: string
  title: string
}
const props = withDefaults(defineProps<Props>(), {
  downloadUrl: '',
  fileName: '',
  visible: false,
  title: '导入标题'
})

const loading = ref(false)

const downloading = ref(false)

const uploader = ref<UploadInstance>() // 上传组件dom

const fileList = ref<UploadUserFile[]>([])

const emits = defineEmits<{
  (e: 'update:visible', visible: boolean): void
  (e: 'success'): void
  (e: 'fail'): void
}>()

const closeDialog = () => {
  uploader.value?.clearFiles()
  emits('update:visible', false)
}

const handleExceed = async (files: File[], uploadFiles: UploadUserFile[]) => {
  ElMessage.warning('请先删除掉上一个文件！')
  return false
}

const beforeUpload = async (file: UploadFile, uploadFiles: UploadFiles) => {
  // 小于30m
  const isLt30M = (file.size ?? 0) / 1024 / 1024 < 30

  if (!isLt30M) {
    ElMessage.error('文件大小不能超过30MB！')
    uploader.value?.handleRemove(file)
    return false
  }

  // TODO .... 其它文件验证

  // 通过验证
  return true
}

const httpRequest = async (item: UploadRequestOptions) => {
  try {
    loading.value = true
    const formData = new FormData()

    for (let i = 0; i < fileList.value.length; i++) {
      const raw = fileList.value[i].raw
      raw && formData.append('file', raw)
    }

    const { code, msg } = await props?.importApi(formData)
    if (code === 1) {
      ElMessage.success(msg || '导入成功')
      // 导入成功
      emits('success')
      closeDialog()
    }
  } catch (error: any) {
    // 导入失败
    emits('fail')
    uploader.value?.clearFiles()
  } finally {
    loading.value = false
  }
}

const onSubmit = () => {
  if (!fileList.value.length) {
    ElMessage.error('请先导入文件')
  } else {
    uploader.value?.submit()
  }
}

const downloadTemplate = async () => {
  downloading.value = true
  await useExport(props.downloadUrl, props.fileName, {}, 'GET').finally(() => {
    downloading.value = false
  })
}
</script>

<style lang="scss">
.import-dialog_container {
  height: 630px;
  width: 800px;
  border-radius: 8px;

  .el-dialog__body {
    padding: calc(var(--el-dialog-padding-primary)) var(--el-dialog-padding-primary);
  }

  .my-header {
    display: flex;
    width: 100%;
    height: 14px;
    left: 0;
    padding-bottom: 17px;
    border-bottom: 1px solid rgb(202, 208, 213);

    .title {
      font-family: 阿里巴巴普惠体;
      font-size: 14px;
      font-weight: 400;
    }
  }

  .upload_container {
    position: relative;
    background: rgb(245, 248, 255);
    border-radius: 4px;
    width: 752px;
    height: 80px;
    padding: 4px;
    margin-bottom: 12px;

    .fontClass {
      position: absolute;
      width: 56px;
      height: 20px;
      margin-left: 16px;
      margin-top: 16px;
      color: rgb(60, 62, 65);
      font-family: 阿里巴巴普惠体;
      font-size: 14px;
      font-weight: 400;
      line-height: 20px;
      letter-spacing: 0px;
      text-align: left;
      display: inline-block;
      align-items: center;
      font-family: 阿里巴巴普惠体;
      font-size: 14px;
      font-weight: 400;
      line-height: 20px;
      letter-spacing: 0px;
      text-align: left;
      display: inline-block;
      align-items: center;
    }

    .tipsClass {
      position: absolute;
      width: 600px;
      height: 20px;
      left: 2.13%;
      right: 26.46%;
      margin-top: 48px;
      bottom: 15%;
      color: rgb(159, 166, 182);
      font-family: 阿里巴巴普惠体;
      font-size: 12px;
      font-weight: 400;
      line-height: 20px;
      letter-spacing: 0px;
      text-align: left;
      display: flex;
      flex-direction: row;
      align-items: center;
    }

    .btnClass {
      width: 120px;
      height: 32px;
      margin-left: 616px;
      margin-top: 36px;
      box-sizing: border-box;
      border-radius: 4px;
    }
  }
}
</style>

<style scoped lang="scss">
.upload-action {
  :deep(.el-upload-list) {
    display: flex;
    overflow: hidden;
    white-space: nowrap;
    padding-top: 10px;
  }

  :deep(.el-icon svg) {
    height: 2em;
    width: 2em;
  }
}

.upload__text {
  color: rgb(60, 62, 65);
  font-family: 阿里巴巴普惠体;
  font-size: 14px;
  font-weight: 400;
  line-height: 12px;
  letter-spacing: 0px;
  text-align: center;
  display: flex;
  flex-direction: row;
  align-items: center;
}

.dialog-footer {
  display: flex;
  width: 90%;
  justify-content: center;
  align-items: center;
  padding: 16px;
  bottom: 0;
  border-top: 1px solid rgb(202, 208, 213);
  position: absolute;

  button:first-child {
    margin-right: 15px;
  }
}

.el-icon--upload {
  width: 750px;
  height: 250px;
  flex-direction: column;
  justify-content: center;
  display: flex;
  align-items: center;
  background: rgb(255, 255, 255);
  border-radius: 4px;
}

.alert_box {
  margin-bottom: 10px;
  height: 25px;
  border-radius: 4px;
}

.uploaded-reminder {
  margin-bottom: 12px;
  padding: 10px;
  display: flex;
  align-items: center;

  .reminder-text {
    color: rgb(92, 95, 102);
  }
}

.success {
  background: rgb(237, 249, 241);
  border: 1px solid rgb(146, 219, 173);
}

.failed {
  justify-content: space-between;
  display: flex;
  align-items: center;
  padding-right: 20px;
  background: rgb(253, 239, 238);
  justify-content: space-between;
  border: 1px solid rgb(241, 163, 155);
}
</style>
